package com.lagou.sqlSession;

import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;

import java.lang.reflect.*;
import java.text.SimpleDateFormat;
import java.util.List;

public class DefaultSqlSession implements Sqlsession {

    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <T> List<T> selectList(String statementId, Object... params) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        List<T> result = simpleExecutor.query(configuration, mappedStatement, params);
        return result;
    }

    @Override
    public <E> E selectOne(String statementId, Object... params) throws Exception {
        List<E> list = this.selectList(statementId, params);
        if(list.size() == 1){
            return (E) list.get(0);
        }else{
            throw new RuntimeException("查询结果为空或查询结果为多条");
        }
    }

    @Override
    public void insert(String statementId, Object... params) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        simpleExecutor.execute(configuration, mappedStatement, params);
    }

    @Override
    public void updateById(String statementId, Object... params) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        simpleExecutor.execute(configuration, mappedStatement, params);
    }

    @Override
    public void deleteById(String statementId, Object... params) throws Exception {
        SimpleExecutor simpleExecutor = new SimpleExecutor();
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        simpleExecutor.execute(configuration, mappedStatement, params);
    }

    @Override
    public <T> T getMapper(Class<?> mapperClass) {

        Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                // 1.底层都是去执行JDBC代码
                // 2.根据不同情况，来调用selectList或selectOne
                String name = method.getName();
                // 通过反射获取到类名
                String className = method.getDeclaringClass().getName();
                String statementId = className +"."+name;

                //获取被调用方法的返回值类型
                Type genericReturnType = method.getGenericReturnType();
                String typeName = genericReturnType.getTypeName();
                //判断是否进行了  泛型类型参数化
                if(genericReturnType instanceof ParameterizedType){
                    List<Object> list = selectList(statementId, objects);
                    return list;
                }
                if(genericReturnType != null && !"void".equals(typeName)){
                    return selectOne(statementId, objects);
                }
                if(name.startsWith("insert")){
                    insert(statementId, objects);
                }
                if(name.startsWith("update")){
                    updateById(statementId, objects);
                }
                if(name.startsWith("delete")){
                    deleteById(statementId, objects);
                }

                return null;
            }
        });
        return (T) proxyInstance;
    }
}
